#include "buzzer.h"

#define ON   1
#define OFF  0

void buzzer_task_handler(BuzzerObjectTypeDef *self, uint32_t period)
{
    if (self->get_ctrl_block(self, &self->ctrl_structure) == 0)
    {
        self->stage = BUZZER_STAGE_START_NEW_CYCLE;
    }

    switch (self->stage)
    {
    case BUZZER_STAGE_START_NEW_CYCLE:
    {
        if (self->ctrl_structure.ticks_on > 0)
        {
            self->set(self, ON);

            if (self->ctrl_structure.ticks_off > 0)
            {
                self->ticks_count = 0;
                self->stage = BUZZER_STAGE_WATTING_OFF;
            }
            else
            {
                self->stage = BUZZER_STAGE_IDLE;
            }
        }
        else
        {
            self->set(self, OFF);
            self->stage = BUZZER_STAGE_IDLE;
        }

        break;
    }

    case BUZZER_STAGE_WATTING_OFF:
    {
        self->ticks_count += period;

        if (self->ticks_count >= self->ctrl_structure.ticks_on)
        {
            self->set(self, OFF);
            self->stage = BUZZER_STAGE_WATTING_PERIOD_END;
        }

        break;
    }

    case BUZZER_STAGE_WATTING_PERIOD_END:
    {
        self->ticks_count += period;

        if (self->ticks_count >= (self->ctrl_structure.ticks_off + self->ctrl_structure.ticks_on))
        {
            self->ticks_count -= (self->ctrl_structure.ticks_off + self->ctrl_structure.ticks_on);

            if (self->ctrl_structure.repeat == 1)
            {
                self->set(self, OFF);
                self->stage = BUZZER_STAGE_IDLE;
            }
            else
            {
                self->set(self, ON);
                self->ctrl_structure.repeat = self->ctrl_structure.repeat == 0 ? 0 : self->ctrl_structure.repeat - 1;
                self->stage = BUZZER_STAGE_WATTING_OFF;
            }
        }

        break;
    }

    case BUZZER_STAGE_IDLE:
    {
        break;
    }

    default:
        break;
    }
}


int buzzer_on( BuzzerObjectTypeDef *self)
{
    BuzzerCtrlTypeDef ctrl_structure =
    {
        .ticks_on = 1,
        .ticks_off = 0,
        .repeat = 0,
    };
    return self->put_ctrl_block(self, &ctrl_structure);
}

int buzzer_off(BuzzerObjectTypeDef *self)
{
    BuzzerCtrlTypeDef ctrl_structure =
    {
        .ticks_on = 0,
        .ticks_off = 0,
        .repeat = 0,
    };
    return self->put_ctrl_block(self, &ctrl_structure);
}

int buzzer_didi(BuzzerObjectTypeDef *self, uint32_t ticks_on, uint32_t ticks_off, uint32_t repeat)
{
    BuzzerCtrlTypeDef ctrl_structure =
    {
        .ticks_on = ticks_on,
        .ticks_off = ticks_off,
        .repeat = repeat,
    };
    return self->put_ctrl_block(self, &ctrl_structure);
}


void buzzer_object_init(BuzzerObjectTypeDef *self)
{
    self->stage = BUZZER_STAGE_IDLE;
}

